-
-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: find references #139
Conversation
I think it's probably fine to leave it "unextracted" for now. I probably want these in the same module anyway, but will name it something different. Can do it later.
You can do this in a later PR if you want, would be better to get any version of this working and released so that the general infrastructure can be used and tested. (same thing i did with go to def basically)
The reference stored in the database should be the expanded alias (I think). You can double check by querying the db with the sqlite3 cli or using a GUI client. So it should "just work" for aliases.
We can optimize this later, feel free to not worry about it for now |
Feel free to post a screen recording if you get a chance, it's always fun to see it in action 😎 |
lib/next_ls.ex
Outdated
SELECT file, start_line, end_line, start_column, end_column | ||
FROM "references" as refs | ||
WHERE refs.identifier = ? | ||
AND refs.arity = ? | ||
AND refs.type = ? | ||
AND refs.module = ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the case that we are finding references for a reference (meaning, a usage of the function, not the definition), we'll want to exclude the reference we're on from the result set.
I think at least, would be valuable to see what other LSPs like gopls and rust analyzer do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ElixirLS doesn't exclude the current reference but we can definitely do it. I'll definitely check what other LSPs do.
I know you are still in progress, but i'll drop a couple of screen recordings of some odd behavior i'm seeing as of now Unrelated results for private function CleanShot.2023-08-05.at.11.24.29.mp4client side exception when finding references of a function definition CleanShot.2023-08-05.at.11.26.59.mp4unrelated results for a remote function CleanShot.2023-08-05.at.11.28.36.mp4 |
Thanks for early the feedback @mhanberg 🙇 I've just pushed another commit that makes the "Find references" functionality work from module/function definitions as well as references (previously it was only working from function references). I thought that I would need Code.Fragment.surround_context/3 but it looks that we have all the information that we need in the Here are a few videos from VSCode with the latest changes: Find references from a function callScreen.Recording.2023-08-06.at.01.04.46.movFind references from a function definitionScreen.Recording.2023-08-06.at.01.07.33.movFind references from a module referenceScreen.Recording.2023-08-06.at.01.06.37.movFind references from a module definitionScreen.Recording.2023-08-06.at.01.08.24.mov |
🤯 Beast mode! |
I've just pushed another commit to extract and improve the symbol information query. We now check if we are in a symbol definition first and fallback to check if we are in a function/module reference otherwise. This logic has been moved into the I plan to test this tomorrow for the entire day in my $DAYJOB, which is a pretty big codebase. If I don't find any stability issues or obvious problems I will update the PR description, remove the draft status and open it for review if that's okay for you @mhanberg |
@crbelaus you are a legend! Thank you so much for this, I'll do a thorough review once you mark as ready, but when I looked yesterday I was already pretty happy. |
I've removed the draft state and this is now ready for review. I've also added a few automated tests to ensure that this works well and doesn't break with future changes. |
test/next_ls_test.exs
Outdated
} | ||
} | ||
], | ||
500 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the timeout for these globally set to 30 seconds, so you can remove all of these custom timeouts, as it's actually making it shorter 😂
https://github.com/elixir-tools/next-ls/blob/main/test/test_helper.exs#L9
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just pushed a commit that removes those explicit timeouts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
lib/next_ls.ex
Outdated
|
||
locations = | ||
dispatch(lsp.assigns.registry, :databases, fn databases -> | ||
for {database, _} <- databases do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are going to flatten it below, you might as well use Enum.flat_map here instead of a comprehension
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are absolutely right! Much better to do it in a single operation since it doesn't hurt readability either.
I've just pushed a commit that replaces the for comprehension with Enum.flat_map
as you suggested.
Just had that one comment, i will test this manually after work and hopefully merge and release before i present at the Denver Elixir Meetup about NextLS, so I can show off your hard work 💪. I assume you'll be asleep at that time but I'll give you the loudest of shoutouts 👏. |
2abd08e
to
b1ba45e
Compare
* Revert "chore: format sql" This reverts commit b25688a. * Revert "fix(references): ignore references to elixir source code" This reverts commit 6ff4c17. * Revert "fix(references): clamp line and column numbers" This reverts commit 55ead79. * Revert "feat: find references (#139)" This reverts commit 5a3b530.
This PR is meant to implement the Find References Request.
The strategy is as follows:
symbols
table to see if we are in a definition:defmodule
,def
,defp
,defmacro
ordefstruct
references
table to see if we are in a function call or in a module alias.references
table to list all known references.I've been using this today at $DAYJOB, which is a pretty big codebase, and everything seems to work just fine. I've also added two automated tests to confirm that the functionality works for finding function and module references.
Closes #43